import { getObjectValue } from '../util/ObjectUtil.js'

const template2Vnode = new Map()
const vnode2Template = new Map()

export function getTemplate2Vnode() {
  return template2Vnode
}

export function getVnode2Template() {
  return vnode2Template
}


/**
*为Hue的原型添加render方法
*@param {Class} Hue 类Hue
*/
export function renderMixin(Hue) {
  Hue.prototype._render = function () {
    renderVnode(this, this._vnode)
  }
}

/**
*更新数据
*@param {Hue} vm 创建的Hue实例
*@param {string} template 模板名
*/
export function renderDate(vm, template) {
  const vnodes = template2Vnode.get(template)
  if (vnodes) {
    for (const vnode of vnodes) {
      renderVnode(vm, vnode)
    }
  }
}

/**
*开始渲染
*@param {Hue} vm 创建的Hue实例
*@param {Object} vnode 虚拟dom树的根节点
*/
function renderVnode(vm, vnode) {
  if (vnode.nodeType === 3) {
    let templates = vnode2Template.get(vnode)
    let result = vnode.text
    if (templates) {
      for (const template of templates) {
        // /[a-zA-Z0-9.,_$]+\([a-zA-Z0-9.,_$]+\)/.test('formatDate(item.date)')
        if (/[a-zA-Z0-9.,_$]+\([a-zA-Z0-9.,_$]+\)/.test(template)) {
          const regex = /\(([^)]+)\)/ // 匹配括号内的内容
          const match = template.match(regex) // 执行正则匹配
          if (match) {
            const param = match[1] // 提取括号中的内容
            const func = template.replace(match[0], '')
            //此种做法只能传一个参数,有多个参数可先split分割后循环，用getTemplate2Value后一个个放数组中，再解构传参
            result = result.replace(`{{${template}}}`, vm[func].call(vm, getTemplate2Value([vm._data, vnode.env], param)))
          } else {
            throw new Error(`${template}错误`)
          }
        } else {
          result = result.replace(`{{${template}}}`, getTemplate2Value([vm._data, vnode.env], template))
        }
      }
      vnode.elm.nodeValue = result
    }
  } else if (vnode.nodeType === 1 && (vnode.tag === "INPUT" || vnode.tag === "TEXTAREA")) {
    let templates = vnode2Template.get(vnode)
    if (templates) {
      for (const template of templates) {
        let result = getTemplate2Value([vm._data, vnode.env], template)
        if (result) vnode.elm.value = result
      }
    }
  } else {
    for (const child of vnode.children) {
      renderVnode(vm, child)
    }
  }
}

/**
*预备渲染，建立映射关系
*@param {Hue} vm 创建的Hue实例
*@param {Object} vnode 虚拟dom树的根节点
*/
export function perpareRander(vm, vnode) {
  if (!vnode) return
  if (vnode.nodeType === 3) {
    analysisTemplateString(vnode, vnode.text)
    return
  } else if (vnode.nodeType === 0) {
    creatTemplate2Vnode(vnode, vnode.data)
    creatVnode2Template(vnode, vnode.data)
  } else if (vnode.nodeType === 1) {
    analysisAttr(vm, vnode)
  }
  for (const child of vnode.children) {
    perpareRander(vm, child)
  }
}

/**
*解析出模板
*@param {Object} vnode 虚拟dom节点
*@param {string} text 文本节点中的内容
*/
function analysisTemplateString(vnode, text) {
  let templateStrings = text.match(/{{[a-zA-Z0-9_.()]+}}/g)
  if (templateStrings instanceof Array) {
    for (const templateString of templateStrings) {
      creatTemplate2Vnode(vnode, getTemplateString(templateString))
      creatVnode2Template(vnode, getTemplateString(templateString))
    }
  }
}

/**
*解析字符串，去除{{}}
*@param {string} templateString 文本节点中的内容
*/
function getTemplateString(templateString) {
  if (templateString
    && templateString.substring(0, 2) === '{{'
    && templateString.substring(templateString.length - 2, templateString.length) == '}}')
    return templateString.substring(2, templateString.length - 2)
  else return templateString
}

/**
*创建映射关系Template->Vnode
*@param {Object} vnode 虚拟dom节点
*@param {string} templateString 解析好的模板字符串
*/
function creatTemplate2Vnode(vnode, templateString) {
  let template4Vnode = template2Vnode.get(templateString)
  if (template4Vnode) {
    template4Vnode.push(vnode)
  } else {
    template2Vnode.set(templateString, [vnode])
  }
}

/**
*创建映射关系Vnode->Template
*@param {Object} vnode 虚拟dom节点
*@param {string} templateString 解析好的模板字符串
*/
function creatVnode2Template(vnode, templateString) {
  let vnode4Template = vnode2Template.get(vnode)
  if (vnode4Template) {
    vnode4Template.push(templateString)
  } else {
    vnode2Template.set(vnode, [templateString])
  }
}

/**
*找出模板对应的值
*@param {Array} objs 对象数组
*@param {string} template 模板名
*/
function getTemplate2Value(objs, template) {
  if (!objs) return null
  for (const obj of objs) {
    let value = getObjectValue(obj, template)
    if (value) return value
  }
  return undefined
}

/**
*清除映射关系
*/
export function clearMap() {
  template2Vnode.clear()
  vnode2Template.clear()
}

/**
*建立v-model映射关系
*@param {Hue} vm 创建的Hue实例
*@param {Object} vnode 虚拟dom树的根节点
*/
function analysisAttr(vm, vnode) {
  if (vnode.nodeType !== 1) return
  const attributeNames = vnode.elm.getAttributeNames()
  if (attributeNames.indexOf('v-model') > -1) {
    creatTemplate2Vnode(vnode, getTemplateString(`{{${vnode.elm.getAttribute('v-model')}}}`))
    creatVnode2Template(vnode, getTemplateString(`{{${vnode.elm.getAttribute('v-model')}}}`))
  }
}